package com.cherry.androidcode.upload

import android.app.Application
import android.net.Uri
import android.util.Log
import android.view.View
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.cherry.androidcode.MainApp
import com.cherry.androidcode.retrofit.RetrofitInstance
import com.cherry.androidcode.util.FileUtil
import com.dylanc.activityresult.launcher.GetMultipleContentsLauncher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.http.*
import rxhttp.toFlow
import rxhttp.toFlowProgress
import rxhttp.wrapper.param.RxHttp
import java.io.File

class UploadExampleViewModel(context: Application) :
    AndroidViewModel(context) {

    val responseLiveData: MutableLiveData<String> = MutableLiveData()

    val downloadLiveData: MutableLiveData<DownloadFile> = MutableLiveData()

    val uploadLiveData: MutableLiveData<UploadFile> = MutableLiveData()

    private val downloadUrlArray = arrayOf(
        "http://update.9158.com/miaolive/Miaolive.apk",//喵播
        //喵播
        "https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk",//探探
        //探探
        "https://o8g2z2sa4.qnssl.com/android/momo_8.18.5_c1.apk",//陌陌
    )


    companion object {
        const val UPLOAD_BASE_URL = "http://192.168.1.5:8080/springmvc/"
        const val UPLOAD_URL = "http://192.168.1.5:8080/springmvc/upload/clientUpload1"
    }

    lateinit var getMultipleContentsLauncher: GetMultipleContentsLauncher


    fun clickRxHttpDownloadFile1(view: View) {
        val file = File(getApplication<MainApp>().applicationContext.filesDir, "test.apk")
        val downloadFile = DownloadFile(file.name, false, 0, 100)
        viewModelScope.launch {
            RxHttp.get(downloadUrlArray[1])
                .toFlowProgress(file.absolutePath, true)
                .catch {
                    downloadFile.error = true
                    downloadLiveData.value = downloadFile
                    Log.w("---", "下载失败---")
                }.collect {
                    val currentProgress = it.progress
                    val currentSize = it.currentSize
                    val totalSize = it.totalSize
                    Log.w("---", "下载中---${currentProgress}----${currentSize}-----${totalSize}")
                    downloadFile.progress = it.progress
                    downloadLiveData.value = downloadFile
                }
        }

    }

    fun clickRxHttpUploadFile2(view: View) {
        selectMultipleVideo { fileList ->
            viewModelScope.launch {
                RxHttp.postForm(UPLOAD_URL)
                    .add("form1", "aa")
                    .add("form2", "bb")
                    .addParts(getApplication(), "file", fileList)
                    .toFlow<HttpResult> {
//                        //上传进度回调,0-100，仅在进度有更新时才会回调
                        val currentProgress = it.progress  //当前进度 0-100
                        val currentSize = it.currentSize //当前已上传的字节大小
                        val totalSize = it.totalSize     //要上传的总字节大小
                        Log.w("---", "上传中---${currentProgress}----${currentSize}-----${totalSize}")
                    }
                    .catch {
                        Log.w("---", "上传失败")
                    }.collect {
                        Log.w("---", it.toString())
                    }
            }
        }
    }

    private fun selectMultipleVideo(uploadVideo: (List<Uri>) -> Unit) {
        getMultipleContentsLauncher.launchForVideo(
            onActivityResult = { uris ->
                if (uris.isNotEmpty()) {
                    uploadVideo(uris)
                }
            },
            onPermissionDenied = { settingsLauncher ->
            },
            onExplainRequestPermission = {
                selectMultipleVideo(uploadVideo)
            }
        )
    }

    private fun selectMultiplePic(
        uploadImageFile: ((List<File>) -> Unit)? = null,
        uploadImageUri: ((List<Uri>) -> Unit)? = null
    ) {
        getMultipleContentsLauncher.launchForImage(
            onActivityResult = { uris ->
                if (uris.isNotEmpty()) {
                    uploadImageFile?.invoke(
                        (uris.mapNotNull { uri ->
                            FileUtil.uri2Path(getApplication(), uri)?.let {
                                File(it)
                            }
                        })
                    )
                    uploadImageUri?.invoke(uris)
                }
            },
            onPermissionDenied = { settingsLauncher ->
            },
            onExplainRequestPermission = {
                selectMultiplePic(uploadImageFile, uploadImageUri)
            }
        )
    }


    fun clickPartByUri1(view: View) {
        val testTextMap = mapOf("form1" to "姓名1", "form2" to "年龄1")
        selectMultiplePic {
            part1Coroutine(
                UploadConvert.convertTextMap(testTextMap),
                UploadConvert.convertFileParamsByUri(getApplication(), "file", it)
            )
        }
    }

    fun clickPartByFile1(view: View) {
        val testTextMap = mapOf("form1" to "姓名1", "form2" to "年龄1")
        selectMultiplePic(uploadImageFile = {
            part1Coroutine(
                UploadConvert.convertTextMap(testTextMap),
                UploadConvert.convertFileParamsByFile("file", it)
            )
        })
    }

    private fun part1Coroutine(
        map: Map<String, @JvmSuppressWildcards RequestBody>,
        fileList: List<MultipartBody.Part>
    ) {
        viewModelScope.launch(Dispatchers.Main) {
            responseLiveData.value = ""
            try {
                val response =
                    RetrofitInstance.defaultInstance(baseurl = UPLOAD_BASE_URL, log = true)
                        .create(UploadTestApi::class.java)
                        .upload1(map, fileList)
                Log.w("response---", response.toString())
                if (response.code == 200) {
                    responseLiveData.value = "图片上传成功"
                } else {
                    responseLiveData.value = "图片上传失败"
                }
            } catch (e: Exception) {
                e.printStackTrace()
                responseLiveData.value = "图片上传失败，网络原因"
            }
        }
    }

    fun clickPartByUri2(view: View) {
        val testTextMap = mapOf("form1" to "姓名1", "form2" to "年龄1")
        selectMultiplePic {
            part2Coroutine(arrayListOf<MultipartBody.Part>().apply {
                addAll(UploadConvert.convertTextPart(testTextMap))
                addAll(UploadConvert.convertFileParamsByUri(getApplication(), "file", it))
            })
        }
    }

    fun clickPartByFile2(view: View) {
        val testTextMap = mapOf("form1" to "姓名1", "form2" to "年龄1")
        selectMultiplePic(uploadImageFile = {
            part2Coroutine(arrayListOf<MultipartBody.Part>().apply {
                addAll(UploadConvert.convertTextPart(testTextMap))
                addAll(UploadConvert.convertFileParamsByFile("file", it))
            })
        })
    }


    private fun part2Coroutine(
        partList: List<MultipartBody.Part>
    ) {
        viewModelScope.launch(Dispatchers.Main) {
            responseLiveData.value = ""
            try {
                val response =
                    RetrofitInstance.defaultInstance(baseurl = UPLOAD_BASE_URL, log = true)
                        .create(UploadTestApi::class.java)
                        .upload2(partList)
                Log.w("response---", response.toString())
                if (response.code == 200) {
                    responseLiveData.value = "图片上传成功"
                } else {
                    responseLiveData.value = "图片上传失败"
                }
            } catch (e: Exception) {
                e.printStackTrace()
                responseLiveData.value = "图片上传失败，网络原因"
            }
        }
    }


    fun clickRequestBodyByUri(view: View) {
        val testTextMap = mapOf("form1" to "姓名1", "form2" to "年龄1")
        selectMultiplePic {
            val uploadFile = UploadFile()
            uploadFile.uri = it
            requestBodyCoroutine(

                UploadConvert.convertRequestBodyByUri(
                    getApplication(),
                    testTextMap,
                    "file",
                    it
                ) { progress, currentSize, totalSize ->
                    //子线程
                    uploadFile.progress = progress
                    uploadFile.currentSize = currentSize
                    uploadFile.totalSize = totalSize
                    uploadLiveData.postValue(uploadFile)
                }
            )
        }
    }


    fun clickRequestBodyByFile(view: View) {
        val testTextMap = mapOf("form1" to "姓名2", "form2" to "年龄2")
        selectMultiplePic(uploadImageFile = {
            requestBodyCoroutine(
                UploadConvert.convertRequestBodyByFile(testTextMap, "file", it)
            )
        })
    }

    private fun requestBodyCoroutine(
        requestBody: RequestBody
    ) {
        viewModelScope.launch(Dispatchers.Main) {
            responseLiveData.value = ""
            try {
                val response =
                    RetrofitInstance.defaultInstance(baseurl = UPLOAD_BASE_URL, log = false)
                        .create(UploadTestApi::class.java)
                        .upload3(requestBody)
                Log.w("response---", response.toString())
                if (response.code == 200) {
                    responseLiveData.value = "图片上传成功"
                } else {
                    responseLiveData.value = "图片上传失败"
                }
            } catch (e: Exception) {
                e.printStackTrace()
                responseLiveData.value = "图片上传失败，网络原因"
            }
        }
    }


    interface UploadTestApi {
        @Multipart
        @POST("upload/clientUpload1")
        suspend fun upload1(
            @PartMap map: Map<String, @JvmSuppressWildcards RequestBody>,
            @Part file: List<MultipartBody.Part>
        ): HttpResult

        @Multipart
        @POST("upload/clientUpload1")
        suspend fun upload2(
            @Part partList: List<MultipartBody.Part>
        ): HttpResult

        //RequestBody方式 Content-Type: multipart/mixed; 需要手动设置
        @POST("upload/clientUpload1")
        suspend fun upload3(@Body body: RequestBody): HttpResult
    }

    data class HttpResult(val code: Int, val message: String)

    data class UploadFile(
        var uri: List<Uri>? = null,
        var file: List<File>? = null,
        var progress: Int = 0,
        var currentSize: Long = 0L,
        var totalSize: Long = 0L
    )

    data class DownloadFile(
        val fileName: String,
        var error: Boolean,
        var progress: Int = 0,
        val maxSize: Int
    )

/*
*  @Test
public void uploadFile1() {
    final Map<String, String> params = new HashMap<>();
    params.put("slaughterInfoId", "245e2babc50311eba3706c4b90188f37");
    params.put("userId", "ae8e1f6d9bff40a2ab625190618a2a95");
    params.put("weight", "100");
    params.put("earmark", "123456789012345");
    params.put("weightDate", "2021-05-06 10:21:57");
    params.put("remark", "测试上传文件");

    final HashMap<String, RequestBody> map = new HashMap<>();
    //文本信息
    params.forEach((key, value) -> {
        final RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), value);
        map.put(key, requestBody);
    });

    //电脑的本机测试文件
    final File file = new File("C:\\Users\\lenovo\\Desktop\\ear_tag.jpg");
    System.out.println(file + "--------");
    RequestBody fileRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), fileRequestBody);

    Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(" http://localhost:8080/springmvc_war/")
            .client(new OkHttpClient.Builder().addInterceptor(new LogInterceptor()).build())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    final Retrofit retrofit = builder.addConverterFactory(GsonConverterFactory.create(Json.getInstance().gson)).build();

    retrofit.create(Api.class).upload1(map, filePart).subscribe(new Consumer() {
        @Override
        public void accept(Object o) throws Exception {

        }
    }, Throwable::printStackTrace);

    try {
        Thread.sleep(5*1000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Test
public void uploadFile2() {
    final Map<String, String> params = new HashMap<>();
    params.put("slaughterInfoId", "245e2babc50311eba3706c4b90188f37");
    params.put("userId", "ae8e1f6d9bff40a2ab625190618a2a95");
    params.put("weight", "100");
    params.put("earmark", "123456789012345");
    params.put("weightDate", "2021-05-06 10:21:57");
    params.put("remark", "测试上传文件");

    final MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
    //文本信息
    params.forEach(bodyBuilder::addFormDataPart);

    //电脑的本机测试文件
    final File file = new File("C:\\Users\\lenovo\\Desktop\\1111.jpg");
    System.out.println(file + "--------");
    RequestBody fileRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    //第一个参数表示分块中的key，及name=‘’,第二个参数表示分块中的value，即filename=''，第三个参数表示分块中的Content-Type和文件二进制字节
    bodyBuilder.addFormDataPart("file", file.getName(), fileRequestBody);

    Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(" http://localhost:8080/springmvc_war/")
            .client(new OkHttpClient.Builder().addInterceptor(new LogInterceptor()).build())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    final Retrofit retrofit = builder.addConverterFactory(GsonConverterFactory.create(Json.getInstance().gson)).build();

    retrofit.create(Api.class).upload2(bodyBuilder.build()).subscribe(new Consumer() {
        @Override
        public void accept(Object o) throws Exception {

        }
    }, Throwable::printStackTrace);

    try {
        Thread.sleep(5*1000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
* */

}